<HEAD>
  <SCRIPT SRC="../ganja.js"></SCRIPT>
</HEAD>
<BODY><SCRIPT>
// Create a Clifford Algebra with 2,0,1 metric.
Algebra(2,0,1,()=>{

  // Prototype PGA implementation of 2D origami folding.
  // "A Mathematica module for conformal geometric algebra and origami folding"
  // https://easychair.org/publications/paper/8jDf
  
  // First four Huzita-Hatori axioms 
  var Ori1 = (p1,p2)=>p1&p2,
      Ori2 = (p1,p2)=>(p1&p2)<<(p1+p2).Normalized,
      Ori3 = (l1,l2,flag)=>{ l1=l1.Normalized; l2=l2.Normalized; return flag?(l1+l2):(l1+l2)<<(l1^l2)},
      Ori4 = (p1,l1)=>l1.Normalized<<p1.Normalized;

  // Quick and dirty origami fold function. Ignores adjacency/layering. (only performs splitting).
  // Takes a figure O, fold line l, list of faces to fold f. Returns updated O. 
  var Ori = (O,l,f) => {
      var res=[]; O.forEach((s,si)=>{ 
        if (f.indexOf(si)==-1) return res.push(s);                              // no split needed
        var signs = s.map(p=>Math.sign(((p/p.e12)^l).e012.toFixed(2)));         // side of ray points are on
        var t=[]; s.forEach((x,i)=>{                                            // loop over edges
            var j=(i+1)%s.length; t.push(x);                                    // insert vertex
            if (signs[i]&&signs[j]&&signs[i]!=signs[j]) t.push(x&s[j]^l)        // insert cut point
        });
        signs = t.map(p=>Math.sign(((p/p.e12)^l).e012.toFixed(2)));             // recalc signs
        res.push(t.filter((p,i)=>signs[i]<=0).map(x=>l>>>x).map(x=>x/x.e12),    // push turned face
                 t.filter((p,i)=>signs[i]>=0).map(x=>x/x.e12));                 // push split face
      })
      return res;
  }

  // We follow the procedure from the paper to fold Kabuto
  var point = (x,y)=>1e12-x*1e01+y*1e02;
  var s = 0.75, p1 = point(-s,s), p2 = point(-s,-s), p3 = point(s,-s), p4 = point(s,s);
  
  var O0 = [[p1,p2,p3,p4]],
      O1 = Ori(O0,Ori2(p1,p3),[0]),
      O2 = Ori(O1,Ori2(p4,p3),[0,1]),
      O3 = Ori(O2,Ori2(p2,p3),[1,3]);

  var p5=(p1+p3)/2, p6=(p3+p4)/2, p7=(p2+p3)/2,
      O4 = Ori(O3,Ori2(p3,p5),[0,1,3,4]),
      O5 = Ori(O4,Ori2(p6,p5),[5,6]),
      O6 = Ori(O5,Ori2(p7,p5),[9,10]);

  var p8=(p3+p5)/2, p9=(p5+p6)/2, p10=(p5+p7)/2,
      O7 = Ori(O6,Ori3(p8&p5,p9&p8),[7,8]),
      O8 = Ori(O7,Ori3(p5&p8,p8&p10),[13,14]);
      
  var p11=(p8+p5)/2,
      O9 = Ori(O8,Ori2(p3,p11),[17]),
      O10 = Ori(O9,Ori1(p7,p6),[17,18]),
      O11 = Ori(O10,Ori1(p7,p6),[4]);

  var draw = (O)=>[].concat.apply(O.concat([0x666666]),O.map(p=>p.map((e,i,a)=>[e,a[(i+1)%a.length]]))).concat(0xFFFFFF);
  document.body.appendChild(this.graph(["Origami - Kabuto", 0xFFFFFF].concat(
       draw(O0-1e01+1e02), draw(O1-1e01-1e02),
       draw(O2+1.2e01+1.8e02), draw(O3+.7e01+0.8e02),   draw(O4+.7e01-0.2e02), draw(O5+.7e01-1.2e02),
       draw(O6+1.6e01+0.8e02), draw(O7+1.6e01-0.2e02),  draw(O8+1.6e01-1.2e02),
       draw(O9+2.5e01+0.8e02), draw(O10+2.5e01-0.2e02), draw(O11+2.5e01-1.2e02)
  )));
});
</SCRIPT></BODY>